home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
mint
/
mint104s.zoo
/
mint.src
/
filesys.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-03-08
|
28KB
|
1,114 lines
/*
Copyright 1990,1991,1992 Eric R. Smith.
Copyright 1992 Atari Corp.
All rights reserved.
*/
/*
* various file system interface things
*/
#include "mint.h"
#define PATH2COOKIE_DB(x) TRACE(x)
FILESYS *active_fs;
FILESYS *drives[NUM_DRIVES];
extern FILESYS tos_filesys; /* declaration needed for debugging only */
/* "aliased" drives are different names
* for real drives/directories
* if drive d is an alias for c:\usr,
* then alias_drv[3] == 2 (the real
* drive) and aliases has bit (1L << 3)
* set.
* NOTE: if aliasdrv[d] is 0, then d is not an aliased drive,
* otherwise d is aliased to drive aliasdrv[d]-1
* (e.g. if drive A: is aliased to B:\FOO, then
* aliasdrv[0] == 'B'-'A'+1 == 2). Always remember to
* compensate for the extra 1 when dereferencing aliasdrv!
*/
int aliasdrv[NUM_DRIVES];
FILEPTR *flist; /* a list of free file pointers */
char follow_links[1]; /* dummy "name" used as a parameter to path2cookie */
/* vector of valid drives, according to GEMDOS */
/* note that this isn't necessarily the same as what the BIOS thinks of
* as valid
*/
long dosdrvs;
/*
* Initialize a specific drive. This is called whenever a new drive
* is accessed, or when media change occurs on an old drive.
* Assumption: at this point, active_fs is a valid pointer
* to a list of file systems.
*/
/* table of processes holding locks on drives */
extern PROC *dlockproc[]; /* in dosdir.c */
void
init_drive(i)
int i;
{
long r;
FILESYS *fs;
fcookie root_dir;
TRACE(("init_drive(%c)", i+'A'));
drives[i] = 0; /* no file system */
if (i >= 0 && i < NUM_DRIVES) {
if (dlockproc[i]) return;
}
for (fs = active_fs; fs; fs = fs->next) {
r = (*fs->root)(i, &root_dir);
if (r == 0) {
drives[i] = root_dir.fs;
release_cookie(&root_dir);
break;
}
}
}
/*
* initialize the file system
*/
#define NUMFPS 40 /* initial number of file pointers */
void
init_filesys()
{
static FILEPTR initial[NUMFPS+1];
int i;
extern FILESYS tos_filesys, bios_filesys, pipe_filesys,
proc_filesys, uni_filesys;
/* get the vector of connected GEMDOS drives */
dosdrvs = Dsetdrv(Dgetdrv()) | drvmap();
/* set up some initial file pointers */
for (i = 0; i < NUMFPS; i++) {
initial[i].devinfo = (ulong) (&initial[i+1]);
}
initial[NUMFPS].devinfo = 0;
flist = initial;
/* set up the file systems */
tos_filesys.next = 0;
bios_filesys.next = &tos_filesys;
pipe_filesys.next = &bios_filesys;
proc_filesys.next = &pipe_filesys;
uni_filesys.next = &proc_filesys;
active_fs = &uni_filesys;
/* initialize the BIOS file system */
biosfs_init();
/* initialize the unified file system */
unifs_init();
}
/*
* load file systems from disk
* this routine is called after process 0 is set up, but before any user
* processes are run
*
* NOTE that a number of directory changes take place here: we look first
* in the current directory, then in the directory \mint, and finally
* the d_lock() calls force us into the root directory.
*/
typedef FILESYS * ARGS_ON_STACK (*FSFUNC) P_((struct kerinfo *));
void
load_filesys()
{
long r;
BASEPAGE *b;
FILESYS *fs;
FSFUNC initf;
static DTABUF dta;
int i;
extern struct kerinfo kernelinfo; /* in main.c */
char curpath[PATH_MAX];
MEMREGION *xfsreg;
#define NPATHS 3
static const char *paths[NPATHS] = {"", "\\MINT", "\\MULTITOS"};
curproc->dta = &dta;
d_getpath(curpath,0);
for (i = 0; i < NPATHS; i++) {
if (*paths[i]) {
/* don't bother checking the current directory twice! */
if (!stricmp(paths[i],curpath))
r = -1;
else
r = d_setpath(paths[i]);
}
else
r = 0;
if (r == 0)
r = f_sfirst("*.xfs", 0);
while (r == 0) {
b = (BASEPAGE *)p_exec(3, dta.dta_name, (char *)"", (char *)0);
if ( ((long)b) < 0 ) {
DEBUG(("Error loading file system %s", dta.dta_name));
r = f_snext();
continue;
}
/* we leave a little bit of slop at the end of the loaded stuff */
m_shrink(0, (virtaddr)b, 512 + b->p_tlen + b->p_dlen + b->p_blen);
initf = (FSFUNC)b->p_tbase;
TRACE(("initializing %s", dta.dta_name));
fs = (*initf)(&kernelinfo);
if (fs) {
TRACE(("%s loaded OK", dta.dta_name));
/* put the loaded XFS into super accesible memory */
xfsreg = addr2region( (long) b );
mark_region(xfsreg, PROT_S);
/* link it into the list of drivers */
fs->next = active_fs;
active_fs = fs;
} else {
DEBUG(("%s returned null", dta.dta_name));
m_free((virtaddr)b);
}
r = f_snext();
}
}
/* here, we invalidate all old drives EXCEPT for ones we're already using (at
* this point, only the bios devices should be open)
* this gives newly loaded file systems a chance to replace the
* default tosfs.c
*/
for (i = 0; i < NUM_DRIVES; i++) {
if (d_lock(1, i) == 0) /* lock if possible */
d_lock(0, i); /* and then unlock */
}
}
void
close_filesys()
{
PROC *p;
FILEPTR *f;
int i;
TRACE(("close_filesys"));
/* close every open file */
for (p = proclist; p; p = p->gl_next) {
for (i = MIN_HANDLE; i < MAX_OPEN; i++) {
if ( (f = p->handle[i]) != 0) {
if (p->wait_q == TSR_Q || p->wait_q == ZOMBIE_Q)
ALERT("Open file for dead process?");
do_pclose(p, f);
}
}
}
}
/*
* "media change" routine: called when a media change is detected on device
* d, which may or may not be a BIOS device. All handles associated with
* the device are closed, and all directories invalidated. This routine
* does all the dirty work, and is called automatically when
* disk_changed detects a media change.
*/
void ARGS_ON_STACK
changedrv(d)
unsigned d;
{
PROC *p;
int i;
FILEPTR *f;
FILESYS *fs;
SHTEXT *stext;
extern SHTEXT *text_reg; /* in mem.c */
DIR *dirh;
fcookie dir;
int warned = (d & 0xf000) == PROC_BASE_DEV;
long r;
/* if an aliased drive, change the *real* device */
if (d < NUM_DRIVES && aliasdrv[d]) {
d = aliasdrv[d] - 1; /* see NOTE above */
}
/* re-initialize the device, if it was a BIOS device */
if (d < NUM_DRIVES) {
fs = drives[d];
if (fs) {
(void)(*fs->dskchng)(d);
}
init_drive(d);
}
for (p = proclist; p; p = p->gl_next) {
/* invalidate all open files on this device */
for (i = MIN_HANDLE; i < MAX_OPEN; i++) {
if (((f = p->handle[i]) != 0) && (f->fc.dev == d)) {
if (!warned) {
ALERT(
"Files were open on a changed drive (0x%x)!", d);
warned++;
}
/* we set f->dev to NULL to indicate to do_pclose that this is an
* emergency close, and that it shouldn't try to make any
* calls to the device driver since the file has gone away
*/
f->dev = NULL;
(void)do_pclose(p, f);
/* we could just zero the handle, but this could lead to confusion if
* a process doesn't realize that there's been a media change, Fopens
* a new file, and gets the same handle back. So, we force the
* handle to point to /dev/null.
*/
p->handle[i] =
do_open("U:\\DEV\\NULL", O_RDWR, 0, (XATTR *)0);
}
}
/* terminate any active directory searches on the drive */
/* BUG: This handles only Fsfirst/Fsnext searches! */
for (i = 0; i < NUM_SEARCH; i++) {
dirh = &p->srchdir[i];
if (dirh->fc.fs && dirh->fc.dev == d) {
TRACE(("closing search for process %d", p->pid));
release_cookie(&dirh->fc);
dirh->fc.fs = 0;
p->srchdta[i] = 0;
}
}
if (d >= NUM_DRIVES) continue;
/* change any active directories on the device to the (new) root */
fs = drives[d];
if (fs) {
r = (*fs->root)(d, &dir);
if (r != E_OK) dir.fs = 0;
} else {
dir.fs = 0; dir.dev = d;
}
for (i = 0; i < NUM_DRIVES; i++) {
if (p->root[i].dev == d) {
release_cookie(&p->root[i]);
dup_cookie(&p->root[i], &dir);
}
if (p->curdir[i].dev == d) {
release_cookie(&p->curdir[i]);
dup_cookie(&p->curdir[i], &dir);
}
}
release_cookie(&dir);
}
/* free any file descriptors associated with shared text regions */
for (stext = t